package cn.ad.server.web.spring.service.components.adtraffic2;

import cn.ad.server.common.utils.EncodeUtils;
import cn.ad.server.web.spring.model.gdt.server.*;
import cn.ad.server.web.spring.model.sts.STSAdResponse;
import cn.ad.server.web.spring.service.actions.context.AdContext;
import cn.ad.server.web.spring.service.actions.handler.gdt.server.HttpConnectionManager;
import cn.ad.server.web.spring.service.components.adtraffic.GDTTrafficDispatcher;
import cn.ad.server.web.utils.JsonUtils;
import cn.ad.server.domain.ad.AdSpaceAdxMap;
import cn.ad.server.domain.ad.AdTemplate;
import cn.ad.server.domain.ad.AdTemplateSpec;
import cn.ad.server.domain.enumration.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.HttpStatus;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigDecimal;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * Created by zooy on 17-1-12.
 */
@Component
public class GDTSSPDispatcher extends AbstractGDTDispatcher implements SSPDispatcher {

    private static Logger logger = LoggerFactory.getLogger(GDTTrafficDispatcher.class);

    private final String impAddress = "http://v.gdt.qq.com/gdt_stats.fcg";

    private final String clickAddress = "http://c.gdt.qq.com/gdt_mclick.fcg";

    private final String requestAddress = "http://mi.gdt.qq.com/gdt_mview.fcg?";

    @Resource
    private String serverAddress;

    @Autowired
    private HttpConnectionManager httpConnectionManager;

    @Override
    public STSAdResponse.AdSpace request(AdContext adContext, STSAdResponse.AdSpace adSpace, AdTemplate adTemplate, AdSpaceAdxMap adSpaceAdxMap) {

        // 设置转发失败
        adContext.setForwardType(2);
        Map<String, Object> allParam = compositeParam(adContext, adSpaceAdxMap);
        Map<String, Object> param = (Map<String, Object>) allParam.get("param");
        Map<String, String> specMap = (Map<String, String>) allParam.get("spec");

        CloseableHttpClient httpClient = httpConnectionManager.getHttpClient();
        HttpGet httpGet = new HttpGet(requestAddress + generateParam(param));
        InputStream ins = null;
        try {
            CloseableHttpResponse response = httpClient.execute(httpGet);

            ins = response.getEntity().getContent();
            if (HttpStatus.SC_OK == response.getStatusLine().getStatusCode()) {
                //拼接返回参数
                Map result = JsonUtils.toObject(ins, Map.class);
                if ((int) result.get("ret") == 0) {
                    Object imp = ((Map) result.get("data")).get(param.get("posid"));
                    if (imp != null) {
                        Map impMap = (Map) imp;
                        List impList = (List) impMap.get("list");
                        if (!CollectionUtils.isEmpty(impList)) {
                            STSAdResponse.Creative[] creatives = new STSAdResponse.Creative[impList.size()];
                            for (int i = 0; i < impList.size(); i++) {
                                Map impEntity = (Map) impList.get(i);
                                STSAdResponse.Creative creative = new STSAdResponse.Creative();
                                creative.setImpression(new String[]{compositeImpUrl((String) impEntity.get("viewid"), param), compositeLocalImpUrl(adContext)});
                                STSAdResponse.Event event = new STSAdResponse.Event();
                                event.setEventKey(ActionType.LINK_JUMP.getValue());
                                if (OS.osMap.get(adContext.getOs()) == OS.IOS) {
                                    event.setEventValue(impEntity.get("rl") + "&acttype=0&s={\"down_x\":-999,\"down_y\":-999,\"up_x\":-999,\"up_y\":-999}");
                                } else {
                                    event.setEventValue(impEntity.get("rl") + "&acttype=&s={\"down_x\":-999,\"down_y\":-999,\"up_x\":-999,\"up_y\":-999}");
                                }
                                creative.setEvent(new STSAdResponse.Event[]{event});
                                creative.setClick(new String[]{compositeLocalClickUrl(adContext)});
                                creative.setAdmark("http://alicdn.lieying.cn/sentshow/imgs/tmp/tsa_ad_logo.png");
                                switch (AdFormat.adFormatMap.get(adContext.getAdFormat())) {

                                    case BANNER:
                                    case TABLE_SCREEN:
                                    case OPEN_SCREEN:
                                        STSAdResponse.Banner banner = new STSAdResponse.Banner();
                                        banner.setWidth((int) param.get("posw"));
                                        banner.setHeight((int) param.get("posh"));
                                        String imgUrl = (String) impEntity.get("img");

                                        String txt = (String) impEntity.get("txt");
                                        String desc = (String) impEntity.get("desc");
                                        if (StringUtils.isNotEmpty(txt) && AdFormat.adFormatMap.get(adSpaceAdxMap.getRequestAdFormat()) != AdFormat.AD_NATIVE) {
                                            return null;
                                        }
                                        if (StringUtils.isNotEmpty(desc) && AdFormat.adFormatMap.get(adSpaceAdxMap.getRequestAdFormat()) != AdFormat.AD_NATIVE) {
                                            return null;
                                        }

                                        if (StringUtils.isEmpty(imgUrl)) {
                                            return null;
                                        } else {
                                            banner.setCreativeUrl(imgUrl);
                                        }
                                        banner.setType(MaterialFormat.JPG.getName());
                                        creative.setBanner(banner);
                                        break;
                                    case VIDEO:
                                        break;
                                    case AD_NATIVE:
                                        //原生读取广告位上面的模版
                                        List<AdTemplateSpec> adTemplateSpecs = adTemplate.getAdTemplateSpecs();
                                        STSAdResponse.AdNative[] adNatives = new STSAdResponse.AdNative[adTemplateSpecs.size()];
                                        STSAdResponse.AdNative adNative = null;
                                        for (int j = 0; j < adTemplateSpecs.size(); j++) {
                                            AdTemplateSpec adTemplateSpec = adTemplateSpecs.get(j);
                                            adNative = new STSAdResponse.AdNative();
                                            adNative.setTemplateId(adTemplateSpec.getAdTemplateId());
                                            adNative.setIndex(adTemplateSpec.getIndex());
                                            adNative.setIndexValue(adTemplateSpec.getIndexValue());
                                            adNative.setRequiredField(adTemplateSpec.getElementType());
                                            adNative.setRequiredValue((String) impEntity.get(specMap.get(adTemplateSpec.getIndexValue())));
                                            //暂时写死成jpg，后期可以改成截取url的后缀
                                            if (adTemplateSpec.getElementType() == ElementType.IMAGE.getValue()) {
                                                adNative.setType(MaterialFormat.JPG.getName());
                                            } else if (adTemplateSpec.getElementType() == ElementType.TEXT.getValue()) {
                                                adNative.setType(MaterialFormat.TEXT.getName());
                                            }
                                            adNatives[j] = adNative;
                                        }
                                        creative.setAdNative(adNatives);
                                        break;
                                    default:
                                        break;
                                }
                                creatives[i] = creative;
                            }
                            adSpace.setCreative(creatives);
                        } else {
                            //处理异常
                            return null;
                        }
                    }
                } else {
                    //处理异常
                    return null;
                }
            } else {
                //处理异常
                return null;
            }
        } catch (IOException e) {
            logger.error("http://mi.gdt.qq.com/gdt_mview.fcg request error");
            //处理异常
            return null;
        }
        adContext.setForwardType(1);
        return adSpace;
    }

    @Override
    public Map<String, Object> compositeParam(AdContext adContext, AdSpaceAdxMap adSpaceAdxMap) {

        Map<String, Object> allParam = new LinkedHashMap<>();
        Map<String, Object> param = new LinkedHashMap<>();
        Map<String, String> specMap = new LinkedHashMap<>();
        param.put("adposcount", "1");
        param.put("count", adContext.getPageSize() == 0 ? 1 : adContext.getPageSize());

        if (AdFormat.adFormatMap.get(adSpaceAdxMap.getRequestAdFormat()) == AdFormat.AD_NATIVE) {
            param.put("posw", 0);
            param.put("posh", 0);
        } else {
            if (adSpaceAdxMap.getWidth() > 0) {
                param.put("posw", adSpaceAdxMap.getWidth());
                param.put("posh", adSpaceAdxMap.getHeight());
            } else {
                param.put("posw", adContext.getAdSpaceWidth());
                param.put("posh", adContext.getAdSpaceHeight());
            }
        }

        String specMapString = adSpaceAdxMap.getSpecMap();
        if (StringUtils.isNotEmpty(specMapString)) {
            for (String spec : specMapString.split(",")) {
                String[] split = spec.split(":");
                specMap.put(split[0], split[1]);
            }

            allParam.put("spec", specMap);
        }

        param.put("posid", adSpaceAdxMap.getAdxSpaceId());
        param.put("charset", "utf8");
        param.put("datafmt", adSpaceAdxMap.getDataFormat() == 0 ? "json" : "html");

        //广告请求扩展内容
        GdtServerExt gdtServerExt = new GdtServerExt();
        GdtServerReq gdtServerReq = new GdtServerReq();

        // 设置request param
        gdtServerReq.setApiver("2.0");

        //AppId
        gdtServerReq.setAppid(adSpaceAdxMap.getAppId());
        gdtServerReq.setC_os(OS.osMap.get(adContext.getOs()).getName());
        if (adContext.getMuniqueType() == MUniqueType.IMEI.getValue()) {
            if (StringUtils.isNotEmpty(adContext.getImeiori())) {
                gdtServerReq.setMuid(EncodeUtils.MD5(adContext.getImeiori().toLowerCase()));
            } else {
                gdtServerReq.setMuid(adContext.getImei());
            }
            gdtServerReq.setMuidtype(GDTMuniqueType.IMEI.getValue());
        } else if (adContext.getMuniqueType() == MUniqueType.IDFA.getValue()) {
            if (StringUtils.isNotEmpty(adContext.getIdfaori())) {
                gdtServerReq.setMuid(EncodeUtils.MD5(adContext.getIdfaori()).toLowerCase());
            } else {
                gdtServerReq.setMuid(adContext.getIdfa());
            }
            gdtServerReq.setMuidtype(GDTMuniqueType.IFA.getValue());
        } else if (adContext.getMuniqueType() == MUniqueType.MAC.getValue()) {
            //优先imei传递
            if (StringUtils.isNotEmpty(adContext.getImeiori())) {
                gdtServerReq.setMuid(EncodeUtils.MD5(adContext.getImeiori().toLowerCase()));
                gdtServerReq.setMuidtype(GDTMuniqueType.IMEI.getValue());
            } else {
                gdtServerReq.setMuid(adContext.getMac());
                gdtServerReq.setMuidtype(GDTMuniqueType.MAC.getValue());
            }
        } else {
            return null;
        }

        //FIXME 填了设备后就不能出广告了
        if (adContext.getBrand() != null) {
            gdtServerReq.setC_device(adContext.getBrand());
        } else if (adContext.getModel() != null) {
            gdtServerReq.setC_device(adContext.getModel());
        } else {
            gdtServerReq.setC_device("unknown");
        }

        //App包名
        gdtServerReq.setC_pkgname(adSpaceAdxMap.getPackageName());
        gdtServerReq.setPostype(GDTServerAdFormat.AD_FORMAT_MAP.get(AdFormat.adFormatMap.get(adSpaceAdxMap.getRequestAdFormat())));
        gdtServerReq.setConn(adContext.getConnType());
        gdtServerReq.setCarrier(adContext.getMob_ops());
        if (adContext.getScreenOritent() == Orientation.CROSS.ordinal()) {
            gdtServerReq.setC_w(adContext.getScreenHeight());
            gdtServerReq.setC_h(adContext.getScreenWidth());
        } else {
            gdtServerReq.setC_w(adContext.getScreenWidth());
            gdtServerReq.setC_h(adContext.getScreenHeight());
        }
        gdtServerReq.setRemoteip(adContext.getIp());
        if (adContext.getLatitude() != 0.0 && adContext.getLongitude() != 0.0) {
            gdtServerReq.setLat(new BigDecimal(adContext.getLatitude() * 1000000).intValue());
            gdtServerReq.setLng(new BigDecimal(adContext.getLongitude() * 1000000).intValue());
        }

        gdtServerReq.setUseragent(adContext.getUa());
        gdtServerReq.setReferer(adContext.getReferer());
        gdtServerReq.setC_osver(adContext.getOsVersion());
        if (StringUtils.isNotEmpty(adContext.getImeiori())) {
            gdtServerReq.setImei(EncodeUtils.MD5(adContext.getImeiori().toLowerCase()));
        }
        if (adContext.getMac() != null) {
            gdtServerReq.setMac(adContext.getMac());
        }
        if (adContext.getAndroidId() != null) {
            gdtServerReq.setAid(adContext.getAndroidId());
        }
        if (adContext.getAaid() != null) {
            gdtServerReq.setAaid(adContext.getAaid());
        }
        if (adContext.getIdfa() != null) {
            gdtServerReq.setIdfa(adContext.getIdfa());
        }

        gdtServerExt.setReq(gdtServerReq);
        param.put("ext", gdtServerExt);

        allParam.put("param", param);

        return allParam;
    }

    private String compositeImpUrl(String viewId, Map param) {

        String impUrlFormat = impAddress + "?count=%s&viewid0=%s";
        return String.format(impUrlFormat, param.get("count"), viewId);
    }

    private String compositeLocalClickUrl(AdContext adContext) {
        String impUrlFormat = serverAddress + "v2/forward/click/ch/3?version=%s&aid=%s&sid=%s";
        return String.format(impUrlFormat, adContext.getVersion(), adContext.getAdSpaceId(), 0);
    }

    private String compositeLocalImpUrl(AdContext adContext) {
        String impUrlFormat = serverAddress + "v2/forward/imp/ch/3?version=%s&aid=%s&sid=%s";
        return String.format(impUrlFormat, adContext.getVersion(), adContext.getAdSpaceId(), 0);
    }

}
